import configparser
from kinyx.type_util import str_to_bool
from kinyx.type_util import str_to_int
from kinyx.file_util import File

class Config:
    def __init__(self, ini_config_file:(str, File)):
        # 参数归一
        if isinstance(ini_config_file, str):
            ini_config_file = File(ini_config_file)
        # 参数校验
        if not isinstance(ini_config_file, File):
            raise ValueError('parameter ini_config_file must be a string or a kinyx.file_util.File.')

        ini_config_file_path = ini_config_file.file_path()

        # 业务校验
        if not ini_config_file.exist():
            raise ValueError(f'file [{ini_config_file_path}] is not exist.')

        self.__ini_config_file_path = ini_config_file_path

        config = configparser.ConfigParser()
        config.read(ini_config_file_path)
        self._config = config

        self._section = None

    def section(self, section:str):
        if section is None: raise ValueError('parameter section can not be None.')
        if not isinstance(section, str):
            raise ValueError('parameter section must be a string.')
        self._section = section

    def __get__(self, section:str, key:str, default:str) -> str:
        try:
            value = self._config.get(section, key)
            return default if value == 'None' else value
        except: return default

    def get_str(self, section:str=None, key:str=None, default:str=None) -> str:
        if key is None: raise ValueError('parameter key can not be None.')
        if not isinstance(key, str):
            raise ValueError('parameter key must be a string.')
        if section is None:
            if self._section is None:
                raise ValueError('parameter section is None and section has not been set before.')
            else:
                return self.__get__(self._section, key, default)
        else:
            if not isinstance(section, str):
                raise ValueError('parameter section must be a string.')
            return self.__get__(section, key, default)

    def __get_other_type__(self, section:str=None, key:str=None, default=None, func=None, t:str=None):
        value = self.get_str(section=section, key=key, default=default)
        if value is None:
            return None
        try:
            return func(value)
        except:
            raise ValueError(f'configed [{section}][{key}]={value}, but it can not convert to {t}.')

    def get_bool(self, section:str=None, key:str=None, default:bool=None) -> bool:
        return self.__get_other_type__(section, key, default, str_to_bool, 'bool')

    def get_int(self, section:str=None, key:str=None, default:int=None) -> int:
        return self.__get_other_type__(section, key, default, str_to_int, 'int')

    def get_float(self, section:str=None, key:str=None, default:float=None) -> float:
        return self.__get_other_type__(section, key, default, str_to_float, 'float')
